﻿using Advantech.Motion;
using AdvantechMontion;
using CommonTool;
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using Tool;
//-----------------------研华板卡-------------------
namespace Motions
{
     class AdvantechMotion:Motions
    {
        public AdvantechMotion(int nCardIndex, string strName, int nMinAxisNo, int nMaxAxisNo)
                  : base(nCardIndex, strName, nMinAxisNo, nMaxAxisNo)
        {
            m_bEnable = false;
        }
        DEV_LIST[] CurAvailableDevs = new DEV_LIST[Motion.MAX_DEVICES];//卡集合
        uint deviceCount = 0;//板卡个数

        List<IntPtr> m_DeviceHandleList = new List<IntPtr>();
        List<IntPtr[]> m_AxishandList = new List<IntPtr[]>();

        bool m_bInit = false;//硬件打开成功标志

        string[] CardNames = new string[4];
        string[] ConfigPaths = new string[4];
        int[] AxisCountList = new int[4];

        public AxisOperator[] AxisList = new AxisOperator[31];
        public List<string> AxisNameList = new List<string>();
        public double[] m_sfScale = new double[31];

        private Dictionary<Axis, bool[]> _axisStatus = new Dictionary<Axis, bool[]>();

        private Dictionary<Axis, double> _axisCmdPositions = new Dictionary<Axis, double>();

        private Dictionary<Axis, double> _axisActPositions = new Dictionary<Axis, double>();

        private Dictionary<Axis, double> _axisActVel = new Dictionary<Axis, double>();

        private Dictionary<Axis, double> _axisActAcc = new Dictionary<Axis, double>();

        private Dictionary<Axis, bool> _axisHome = new Dictionary<Axis, bool>();

      

        public Dictionary<Axis, double> AxisActPositions
        {
            set { this._axisActPositions = value; }
            get { return this._axisActPositions; }
        }
        public enum Axis
        {
            单工位飞拍 = 0,
            吸嘴U1 = 1,
            吸嘴U2 = 2,
            吸嘴U3 = 3,
            双工位飞拍1 = 4,
            吸嘴U4 = 5,
            吸嘴U5 = 6,
            备用轴7 = 7,
            双工位飞拍2 = 8,
            备用轴9 = 9,
            备用轴10 = 10,
            备用轴11 = 11,
            平台搬运X轴 = 12,
            OK搬运Y轴 = 13,
            下料X轴 = 14,
            下料Y轴 = 15,
            下料Z轴 = 16,
            搬运X轴 = 17,
            进料Z轴 = 18,
            出料Z轴 = 19,
            取料定位X轴 = 20,
            取料定位Y轴 = 22,
            上料Y轴 = 23,
            上料Z轴 = 24,
            移栽U轴 = 25,
            移栽Z轴 = 26,
            移栽Y轴 = 27,
            磁通量检测Z轴 = 28,
            接料X2轴 = 29,
            接料X1轴 = 30,
            出料U轴 = 31

        }
        /// <summary>
        /// 板卡初始化
        /// </summary>
        /// <returns></returns>
        public override void InitMotionCard()
        {
            AxisNameList.Clear();
            foreach (Axis a in Enum.GetValues(typeof(Axis)))
            {
                AxisNameList.Add(a.ToString());
            }

            int Result;
            string strTemp;
            try
            {
                //获取板卡
                Result = Motion.mAcm_GetAvailableDevs(CurAvailableDevs, Motion.MAX_DEVICES, ref deviceCount);
                if (Result != (int)ErrorCode.SUCCESS)
                {
                    strTemp = "Get Device Numbers Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "]";
                    MessageBox.Show(strTemp);
                    return;
                }

                CardNames[0] = CurAvailableDevs[0].DeviceName;
                CardNames[1] = CurAvailableDevs[1].DeviceName;
                CardNames[2] = CurAvailableDevs[2].DeviceName;
                CardNames[3] = CurAvailableDevs[3].DeviceName;

                m_DeviceHandleList.Clear();
                m_DeviceHandleList.Add(IntPtr.Zero);
                m_DeviceHandleList.Add(IntPtr.Zero);
                m_DeviceHandleList.Add(IntPtr.Zero);
                m_DeviceHandleList.Add(IntPtr.Zero);

                m_AxishandList.Clear();
                m_AxishandList.Add(new IntPtr[32]);
                m_AxishandList.Add(new IntPtr[32]);
                m_AxishandList.Add(new IntPtr[32]);
                m_AxishandList.Add(new IntPtr[32]);

                ConfigPaths[0] = string.Format("{0}\\Config\\{1}", Application.StartupPath, "1203.cfg");
                ConfigPaths[1] = string.Format("{0}\\Config\\{1}", Application.StartupPath, "1274-M0.cfg");
                ConfigPaths[2] = string.Format("{0}\\Config\\{1}", Application.StartupPath, "1274-M1.cfg");
                ConfigPaths[3] = string.Format("{0}\\Config\\{1}", Application.StartupPath, "1274-M2.cfg");

                AxisCountList[0] = 0;
                AxisCountList[1] = 0;
                AxisCountList[2] = 0;
                AxisCountList[3] = 0;

                bool Card1init = false;
                bool Card2init = false;
                bool Card3init = false;
                bool Card4init = false;

                if (CardNames[0] == "PCI-1203-32AE (M0)" && CardNames[1] == "PCI-1274-12AE (M1)" && CardNames[2] == "PCI-1274-12AE (M12)" && CardNames[3] == "PCI-1274-12AE (M15)")
                { }
                else
                {
                    MessageBox.Show("板卡排序出错", "错误信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                Card2init = OpenCard(1);//1274
                Thread.Sleep(500);
                Card3init = OpenCard(2);//1274
                Thread.Sleep(500);
                Card4init = OpenCard(3);//1274
                Thread.Sleep(500);
                Card1init = OpenCard(0);//1203
                Thread.Sleep(500);

                if (Card1init && Card2init && Card3init && Card4init)
                {
                    m_bInit = true;

                    LoadConfigs();
                    CardIniOK = true;
                    LogView.GetInstance().ShowLog(LogView.LogType.Oper, "板卡打开成功");
                }
                else
                {
                    LogView.GetInstance().ShowLog(LogView.LogType.Error, "板卡打开失败");
                }

                foreach (Axis a in Enum.GetValues(typeof(Axis)))
                {
                    _axisStatus.Add(a, new bool[11]);

                    _axisHome.Add(a, false);

                    _axisCmdPositions.Add(a, 0);

                    _axisActPositions.Add(a, 0);

                }
                for (int i = 0; i < 31; i++)
                {
                    ServoOff(i);
                }                
                //_motionPoints.IniPoints();

                //IniI01();
                //IniI01_1();
                //IniI02();
                //IniI02_1();
                //IniI03();
                //IniI03_1();

                //IniI07();
                //IniI07_1();

                //tAxisPositons = new Thread(UpdatePositions);
                //tAxisPositons.IsBackground = true;
                //tAxisPositons.Start();

                //tAxisIOStaus = new Thread(UpdateIO);
                //tAxisIOStaus.IsBackground = true;
                //tAxisIOStaus.Start();

                //tAxisStaus = new Thread(UpdateAxisStatus);
                //tAxisStaus.IsBackground = true;
                //tAxisStaus.Start();


            }
            catch (Exception ex)
            {

            }
        }

        private bool OpenCard(int cardNum)
        {
            uint Result;
            string strTemp;

            uint AxesPerDev = new uint();
            try
            {
                IntPtr m_DeviceHandle = m_DeviceHandleList[cardNum];
                //打开板卡
                Result = Motion.mAcm_DevOpen(CurAvailableDevs[cardNum].DeviceNum, ref m_DeviceHandle);

                if (Result != (uint)ErrorCode.SUCCESS)
                {
                    strTemp = "Open Device Failed With Error Code[0x" + Convert.ToString(Result, 16) + "]";
                    MessageBox.Show(strTemp);
                    return false;

                }

                m_DeviceHandleList[cardNum] = m_DeviceHandle;

                //获取单张卡 轴个数
                Result = Motion.mAcm_GetU32Property(m_DeviceHandle, (uint)PropertyID.FT_DevAxesCount, ref AxesPerDev);
                if (Result != (uint)ErrorCode.SUCCESS)
                {
                    strTemp = "Get Axis Number Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "]";
                    MessageBox.Show(strTemp);
                    return false;
                }
                AxisCountList[cardNum] = (int)AxesPerDev;//获取每个轴的个数
                if (cardNum == 0)
                {
                    //总线卡需要获取到对应数量的轴
                    if (AxisCountList[cardNum] != 19)
                    {
                        return false;
                    }
                }
                //依次打开每个轴，并将该轴坐标设置为0
                for (int axisNum = 0; axisNum < AxisCountList[cardNum]; axisNum++)
                {
                    Result = Motion.mAcm_AxOpen(m_DeviceHandle, (UInt16)axisNum, ref m_AxishandList[cardNum][axisNum]);

                    if (Result != (uint)ErrorCode.SUCCESS)
                    {
                        strTemp = "Open Axis Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "]";
                        MessageBox.Show(strTemp);
                        return false;
                    }

                    double cmdPosition = 0;
                    Motion.mAcm_AxSetCmdPosition(m_AxishandList[cardNum][axisNum], cmdPosition);
                    Motion.mAcm_AxSetActualPosition(m_AxishandList[cardNum][axisNum], cmdPosition);


                    if (cardNum == 0)//1203
                    {
                        int num = AxisCountList[1] + AxisCountList[2] + AxisCountList[3] + axisNum;
                        AxisList[num] = new AxisOperator();
                        AxisList[num].CardNum = cardNum;
                        AxisList[num].AxisNum = axisNum;
                        AxisList[num].m_IniSts = true;

                        if (num > 30)
                        {
                            AxisList[num].IsHome = true;
                            AxisList[num].AxisName = "";
                        }
                        else
                        {
                            AxisList[num].IsHome = false;
                            AxisList[num].AxisName = AxisNameList[num];
                        }

                        AxisList[num].m_pdfScale = m_sfScale[num];
                        AxisList[num].m_Axishand = m_AxishandList[cardNum][axisNum];
                    }

                    if (cardNum == 1)//1274
                    {
                        int num = axisNum;
                        AxisList[num] = new AxisOperator();
                        AxisList[num].AxisName = AxisNameList[num];
                        AxisList[num].CardNum = cardNum;
                        AxisList[num].AxisNum = axisNum;
                        AxisList[num].m_IniSts = true;
                        AxisList[num].IsHome = false;
                        AxisList[num].m_pdfScale = m_sfScale[num];
                        AxisList[num].m_Axishand = m_AxishandList[cardNum][axisNum];
                    }

                    if (cardNum == 2)//1274-1
                    {
                        int num = AxisCountList[1] + axisNum;
                        AxisList[num] = new AxisOperator();
                        AxisList[num].AxisName = AxisNameList[num];
                        AxisList[num].CardNum = cardNum;
                        AxisList[num].AxisNum = axisNum;
                        AxisList[num].m_IniSts = true;
                        AxisList[num].IsHome = false;
                        AxisList[num].m_pdfScale = m_sfScale[num];
                        AxisList[num].m_Axishand = m_AxishandList[cardNum][axisNum];
                    }
                    if (cardNum == 3)//1274-2
                    {
                        int num = AxisCountList[1] + AxisCountList[2] + axisNum;
                        AxisList[num] = new AxisOperator();
                        AxisList[num].AxisName = AxisNameList[num];
                        AxisList[num].CardNum = cardNum;
                        AxisList[num].AxisNum = axisNum;
                        AxisList[num].m_IniSts = true;
                        AxisList[num].IsHome = false;
                        AxisList[num].m_pdfScale = m_sfScale[num];
                        AxisList[num].m_Axishand = m_AxishandList[cardNum][axisNum];
                    }

                }

                return true;
            }
            catch (Exception)
            {

                return false;

            }
         



        }


        private void LoadConfigs()
        {
            UInt32 Result;
            string strTemp;
            if (m_bInit != true)
            {
                return;
            }

            for (int i = 0; i < ConfigPaths.Length; i++)
            {
                Result = Motion.mAcm_DevLoadConfig(m_DeviceHandleList[i], ConfigPaths[i]);

                Thread.Sleep(500);

                if (Result != (uint)ErrorCode.SUCCESS)
                {
                    strTemp = "Load Config Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "]";
                    MessageBox.Show(strTemp);
                    return;
                }
            }
        }
        /// <summary>
        /// 关闭轴卡
        /// </summary>
        /// <returns></returns>
        public override void DeInitMotionCard()
        {
            UInt16[] usAxisState = new UInt16[64];

            if (m_bInit == true)
            {
                m_bInit = false;
                CardIniOK = false;
                Thread.Sleep(1000);

                for (int i = 0; i < AxisList.Length; i++)
                {
                    Motion.mAcm_AxGetState(AxisList[i].m_Axishand, ref usAxisState[i]);

                    if (usAxisState[i] == (uint)AxisState.STA_AX_ERROR_STOP)
                    {
                        Motion.mAcm_AxResetError(AxisList[i].m_Axishand);
                    }

                    bool arm = false, lmtp = false, lmtn = false, svon = false;
                    AxisList[i].GetAxisStatus(ref arm, ref lmtp, ref lmtn, ref svon);

                    if (svon)
                        AxisList[i].ServoOff();


                    Motion.mAcm_AxStopDec(AxisList[i].m_Axishand);
                    Motion.mAcm_AxClose(ref AxisList[i].m_Axishand);
                }

                CloseCmd(1, 0);

                CloseCmd(2, 0);
                CloseCmd(2, 1);
                CloseCmd(2, 2);
                CloseCmd(2, 3);
                CloseCmd(2, 4);
                CloseCmd(2, 5);
                CloseCmd(2, 6);

                CloseCmd(2, 8);
                CloseCmd(3, 0);
                CloseCmd(3, 1);
                CloseCmd(3, 2);

                CloseCmd(3, 3);

                for (int i = 0; i < deviceCount; i++)
                {
                    IntPtr m_DeviceHandle = m_DeviceHandleList[i];
                    Motion.mAcm_DevClose(ref m_DeviceHandle);
                }

                m_DeviceHandleList.Clear();

                m_AxishandList.Clear();

                AxisCountList[0] = 0;
                AxisCountList[1] = 0;
                AxisCountList[2] = 0;

            }
        }

        /// <summary>
        /// 开启使能
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override void ServoOn(int nAxisNo)
        {
          if (nAxisNo <= AxisList.Length)
            {
                AxisList[nAxisNo].ServoOn();
            }
        }

        /// <summary>
        /// 关闭使能
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override void ServoOff(int nAxisNo)
        {
            if (nAxisNo <= AxisList.Length)
            {
                AxisList[nAxisNo].ServoOff();
            }
        }

        /// <summary>
        /// 清除轴报警信号
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>                   
        public override void ClearAxisAlarm(int nAxisNo)
        {
            if (nAxisNo <= AxisList.Length)
            {
                AxisList[nAxisNo].ResetError();
            }
        }

        /// <summary>
        /// 读取指定轴Busy状态
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override bool GetAxisBusy(int nAxisNo)
        {

            UInt16 AxState = new UInt16();
            //读取当前轴的运行状态
            Motion.mAcm_AxGetState(AxisList[nAxisNo].m_Axishand, ref AxState);
            //short rtn = 0;
            //rtn = LTDMC.dmc_check_done((ushort)m_nCardIndex, (ushort)nAxisNo);//读取轴运动状态 0 运动中 1停止中
            if (AxState != (uint)AxisState.STA_AX_BUSY)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 读取指定轴报警信号
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override bool GetAxisAlarm(int nAxisNo)
        {
            UInt32 Result;
            UInt32 IOStatus = new UInt32();

            if (AxisList[nAxisNo].m_IniSts != true)
            {
                AxisList[nAxisNo].IsHome = false;
                return true;
            }

            //获得轴的状态灯标志位
            Result = Motion.mAcm_AxGetMotionIO(AxisList[nAxisNo].m_Axishand, ref IOStatus);
            if (Result == (uint)ErrorCode.SUCCESS)
            {
                if ((IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0)//伺服报警
                {
                    //代表该信号触发了
                    return true;
                }
                else
                {
                    //代表该信号未触发
                    return false;
                }
            }
            return true;


        }

        /// <summary>
        /// 读取指定轴伺服准备信号
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override bool GetAxisReady(int nAxisNo)
        {
            UInt32 Result;
            UInt32 IOStatus = new UInt32();

            if (AxisList[nAxisNo].m_IniSts != true)
            {
                AxisList[nAxisNo].IsHome = false;
                return false;
            }

            //获得轴的状态灯标志位
            Result = Motion.mAcm_AxGetMotionIO(AxisList[nAxisNo].m_Axishand, ref IOStatus);
            if (Result == (uint)ErrorCode.SUCCESS)
            {
                if ((IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_RDY) > 0)//伺服准备
                {
                    //代表该信号触发了
                    return true;
                }
                else
                {
                    //代表该信号未触发
                    return false;
                }
            }
            return false;
        }

        /// <summary>
        /// 读取轴使能状态
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override bool GetAxisSeverOn(int nAxisNo)
        {
            UInt32 Result;
            UInt32 IOStatus = new UInt32();

            if (AxisList[nAxisNo].m_IniSts != true)
            {
                AxisList[nAxisNo].IsHome = false;
                return false;
            }

            //获得轴的状态灯标志位
            Result = Motion.mAcm_AxGetMotionIO(AxisList[nAxisNo].m_Axishand, ref IOStatus);
            if (Result == (uint)ErrorCode.SUCCESS)
            {
                if ((IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_SVON) > 0)//伺服使能
                {
                    //代表该信号触发了
                    return true;
                }
                else
                {
                    //代表该信号未触发
                    return  false;
                }
            }
       return false;
        }

        /// <summary>
        /// 获取指定轴当前位置，步进电机使用命令坐标，伺服使用编码器坐标
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override double GetAxisActPos(int nAxisNo)
        {            
            UInt32 Result;
            double CurCmd = new double();
            double ActCmd = new double();
            double Axvel = new double();
            double axacc = new double();
            //获得轴发出的命令坐标跟编码器反馈坐标
            Result = Motion.mAcm_AxGetCmdPosition(AxisList[nAxisNo].m_Axishand, ref CurCmd);
            Result = Motion.mAcm_AxGetActualPosition(AxisList[nAxisNo].m_Axishand, ref ActCmd);
            Result = Motion.mAcm_AxGetCmdVelocity(AxisList[nAxisNo].m_Axishand, ref Axvel);
            Result = Motion.mAcm_GetF64Property(AxisList[nAxisNo].m_Axishand, (uint)PropertyID.PAR_AxAcc, ref axacc);

            if (nAxisNo==1|| nAxisNo == 2 || nAxisNo == 3 || nAxisNo == 6 || nAxisNo == 7)
            {
                return CurCmd / SystemCfg.AxisCfg[nAxisNo].PluseRatio;
            }
            else
            {
                return ActCmd / SystemCfg.AxisCfg[nAxisNo].PluseRatio;
            }
           
        }

        /// <summary>
        /// 获取指定轴命令位置
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override double GetAxisPrfPos(int nAxisNo)
        {
            UInt32 Result;
            double CurCmd = new double();
            double ActCmd = new double();
            double Axvel = new double();
            double axacc = new double();
            //获得轴发出的命令坐标跟编码器反馈坐标
            Result = Motion.mAcm_AxGetCmdPosition(AxisList[nAxisNo].m_Axishand, ref CurCmd);
            Result = Motion.mAcm_AxGetActualPosition(AxisList[nAxisNo].m_Axishand, ref ActCmd);
            Result = Motion.mAcm_AxGetCmdVelocity(AxisList[nAxisNo].m_Axishand, ref Axvel);
            Result = Motion.mAcm_GetF64Property(AxisList[nAxisNo].m_Axishand, (uint)PropertyID.PAR_AxAcc, ref axacc);
            return CurCmd / SystemCfg.AxisCfg[nAxisNo].PluseRatio;
        }

        /// <summary>
        /// 获取轴定位完成信号  !负极限 !正极限 !轴报警 !轴忙 轴使能
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override bool GetAxisDone(int nAxisNo)
        {
            //负极限 正极限 轴报警 轴忙 轴使能
            if (!GetNegLimit(nAxisNo) && !GetPosLimit(nAxisNo) && !GetAxisAlarm(nAxisNo) && GetAxisSeverOn(nAxisNo))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 读取指定轴原点信号
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override bool GetAxisHome(int nAxisNo)
        {
            UInt32 Result;
            UInt32 IOStatus = new UInt32();

            if (AxisList[nAxisNo].m_IniSts != true)
            {
                AxisList[nAxisNo].IsHome = false;
                return false;
            }

            //获得轴的状态灯标志位
            Result = Motion.mAcm_AxGetMotionIO(AxisList[nAxisNo].m_Axishand, ref IOStatus);
            if (Result == (uint)ErrorCode.SUCCESS)
            {
                if ((IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ORG) > 0)//伺服使能
                {
                    //代表该信号触发了
                    return true;
                }
                else
                {
                    //代表该信号未触发
                    return false;
                }
            }
            return false;
        }

        /// <summary>
        /// 读取指定轴负极限
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override bool GetNegLimit(int nAxisNo)
        {
            UInt32 Result;
            UInt32 IOStatus = new UInt32();

            if (AxisList[nAxisNo].m_IniSts != true)
            {
                AxisList[nAxisNo].IsHome = false;
                return true;
            }

            //获得轴的状态灯标志位
            Result = Motion.mAcm_AxGetMotionIO(AxisList[nAxisNo].m_Axishand, ref IOStatus);
            if (Result == (uint)ErrorCode.SUCCESS)
            {
                if ((IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTN) > 0)//伺服使能
                {
                    //代表该信号触发了
                    return true;
                }
                else
                {
                    //代表该信号未触发
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 读取指定轴正极限
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override bool GetPosLimit(int nAxisNo)
        {
            UInt32 Result;
            UInt32 IOStatus = new UInt32();

            if (AxisList[nAxisNo].m_IniSts != true)
            {
                AxisList[nAxisNo].IsHome = false;
                return true;
            }

            //获得轴的状态灯标志位
            Result = Motion.mAcm_AxGetMotionIO(AxisList[nAxisNo].m_Axishand, ref IOStatus);
            if (Result == (uint)ErrorCode.SUCCESS)
            {
                if ((IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTP) > 0)//伺服使能
                {
                    //代表该信号触发了
                    return true;
                }
                else
                {
                    //代表该信号未触发
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 指定轴减速停止
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override void StopAxis(int nAxisNo)
        {

            uint Result;
            string strTemp;
            if (m_bInit != true)
            {
                return;
            }
            if (AxisList[nAxisNo].m_IniSts)
            {
                //To command axis to decelerate to stop.
                Result = Motion.mAcm_AxStopDec(AxisList[nAxisNo].m_Axishand);
                if (Result != (uint)ErrorCode.SUCCESS)
                {
                    strTemp = "Axis To decelerate Stop Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "]";
                    MessageBox.Show(strTemp);
                    return;
                }
            }
            return;
        }

        /// <summary>
        /// 指定轴紧急停止
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override void EmgAxis(int nAxisNo)
        {

            uint Result;
            string strTemp;
            if (m_bInit != true)
            {
                return;
            }
            if (AxisList[nAxisNo].m_IniSts)
            {
                //To command axis to decelerate to stop.
                Result = Motion.mAcm_AxStopEmg(AxisList[nAxisNo].m_Axishand);
                if (Result != (uint)ErrorCode.SUCCESS)
                {
                    strTemp = "Axis To decelerate Stop Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "]";
                    MessageBox.Show(strTemp);
                    return;
                }
            }
            return;
        }

        /// <summary>
        /// 指定轴位置清零
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <returns></returns>
        public override void SetPosZero(int nAxisNo)
        {
            if (m_bInit != true)
            {
                return;
            }
            AxisList[nAxisNo].ClearPos();         
        }

        /// <summary>
        /// 读取输入信号
        /// </summary>
        /// <param name="nIndex"></param>
        /// <returns></returns>
        public override bool ReadIn(int nCardN0, int nIndex)
        {
            if (m_bInit != true)
            {
                return false;
            }

            UInt32 Result;
            byte BitIn = 0;
            ushort DiNumber = (ushort)(nIndex+ nCardN0*8);

            //读取板卡上带的Di信号，DiNumber计算方式=PortNo*8+bit号，DiStatus为0代表未触发，1代表触发了。
            Result = Motion.mAcm_DaqDiGetBit(m_DeviceHandleList[0], DiNumber, ref BitIn);

            if (BitIn == 1)
                return true;
            else if (BitIn == 0)
                return false;
            else
                return false;
        }

        /// <summary>
        /// 读取输出信号
        /// </summary>
        /// <param name="nIndex"></param>
        /// <returns></returns>
        public override bool ReadOut(int nCardN0, int nIndex)
        {
            if (m_bInit != true)
            {
                return false;
            }

            UInt32 Result;
            byte bitDo = 0;
            ushort DoNumber = (ushort)(nIndex + nCardN0 * 8);

            Result = Motion.mAcm_DaqDoGetBit(m_DeviceHandleList[0], DoNumber, ref bitDo);

            if (bitDo == 1)
                return true;
            else if (bitDo == 0)
                return false;
            else
                return false;
        }

        /// <summary>
        /// 输出信号
        /// </summary>
        /// <param name="nIndex"></param>
        /// <param name="bBit"></param>
        /// <returns></returns>
        public override void WriteOut(int nCardN0,int nIndex, bool bBit)
        {
            UInt32 Result;
            string strTemp;

            ushort DoNumber = (ushort)(nIndex + nCardN0 * 8);

            IntPtr m_DeviceHandle = m_DeviceHandleList[0];
            byte b;
            if (bBit)
            {
                b = 1;
            }
            else
            {
                b = 0;
            }
            //写入板卡上带的DO信号，DONumber计算方式=PortNo*8+bit号，DoStatus为1时代表打开，0时代表关闭。
            Result = Motion.mAcm_DaqDoSetBit(m_DeviceHandle, DoNumber, b);

            if (Result != (uint)ErrorCode.SUCCESS)
            {
                //strTemp = "输出信号失败 With Error Code: [0x" + Convert.ToString(Result, 16) + "]";

                //ShowMessages(strTemp, Result);
                //return false;
            }

            //return true;
        }

        /// <summary>
        /// 指定轴绝对位置移动
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <param name="nPos"></param>
        /// <param name="nSpeed"></param>
        /// <returns></returns>
        public override void AbsMove(int nAxisNo, double Pos, double Speed)
        {

            short rtn = 0;
            ClearAxisAlarm(nAxisNo);
            double acc = SystemCfg.AxisCfg[nAxisNo].Acc * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//加速时间
            double dec = SystemCfg.AxisCfg[nAxisNo].Dec * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//减速时间
            double start = SystemCfg.AxisCfg[nAxisNo].StartSpeed * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//起始速度
            double nPos = Pos * SystemCfg.AxisCfg[nAxisNo].PluseRatio;
            double nSpeed = Speed * SystemCfg.AxisCfg[nAxisNo].PluseRatio;
            //起始速度 最大速度 加速度 减速度 停止速度 目标位置 是否等待
            AxisList[(short)nAxisNo].Move_PTP_Abs(start, nSpeed, acc, dec, nPos,false);
            if (rtn != 0)
            {
                //MessageBox.Show(string.Format("雷赛控制卡绝对定位失败 卡号 轴号 原因{0}{1}{2}", m_nCardIndex, nAxisNo, rtn));
                //LogView.GetInstance().ShowLog(LogView.LogType.Error, string.Format("雷赛控制卡绝对定位失败 卡号 轴号 原因{0}{1}{2}", m_nCardIndex, nAxisNo, rtn));
            }
        }

        /// <summary>
        /// 指定轴相对运动
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <param name="nPos"></param>
        /// <param name="nSpeed"></param>
        /// <returns></returns>
        public override void RelMove(int nAxisNo, double Pos, double Speed)
        {

            short rtn = 0;
          
            double acc = SystemCfg.AxisCfg[nAxisNo].Acc * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//加速时间
            double dec = SystemCfg.AxisCfg[nAxisNo].Dec * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//减速时间
            double start = SystemCfg.AxisCfg[nAxisNo].StartSpeed * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//起始速度
            double nPos = Pos * SystemCfg.AxisCfg[nAxisNo].PluseRatio;
            double nSpeed = Speed * SystemCfg.AxisCfg[nAxisNo].PluseRatio;
            ////起始速度 最大速度 加速度 减速度 停止速度 
            //rtn += LTDMC.dmc_set_profile_unit((ushort)m_nCardIndex, (ushort)nAxisNo, start, nSpeed, acc, dec, 0);
            //// 卡号 轴号 目标位置  运动模式 0 相对运动 1 绝对运动
            //rtn += LTDMC.dmc_pmove_unit((ushort)m_nCardIndex, (ushort)nAxisNo, nPos, 0);
            AxisList[(short)nAxisNo].Move_PTP_Rel(start, nSpeed, acc, dec, nPos);
            if (rtn != 0)
            {
                //MessageBox.Show(string.Format("雷赛控制卡相对定位失败 卡号 轴号 原因{0}{1}{2}", m_nCardIndex, nAxisNo, rtn));
                //LogView.GetInstance().ShowLog(LogView.LogType.Error, string.Format("雷赛控制卡相对定位失败 卡号 轴号 原因{0}{1}{2}", m_nCardIndex, nAxisNo, rtn));
            }

        }

        /// <summary>
        /// 指定轴Jog运动
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <param name="nSpeed"></param>
        /// <param name="bPositive"></param>
        /// <returns></returns>
        public override void JogMove(int nAxisNo, double Speed, bool MovDir)
        {
            short rtn = 0;

            //rtn += LTDMC.dmc_stop((ushort)m_nCardIndex, (ushort)nAxisNo, 1);//0 减速停止 1紧急停止
            //Thread.Sleep(5);
            double acc = SystemCfg.AxisCfg[nAxisNo].Acc * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//加速时间
            double dec = SystemCfg.AxisCfg[nAxisNo].Dec * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//减速时间
            double start = SystemCfg.AxisCfg[nAxisNo].StartSpeed * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//起始速度
            double nSpeed = Speed * SystemCfg.AxisCfg[nAxisNo].PluseRatio;
            int on_off = 2;
            if (MovDir == true)
            {
                on_off = 0;
            }
            else
            {
                on_off = 1;
            }
            AxisList[(short)nAxisNo].Move_Jog_MoveVel(start, nSpeed, acc, (ushort)on_off);
          
            if (rtn != 0)
            {
                //MessageBox.Show(string.Format("雷赛控制卡Jog运动失败 卡号 轴号 原因{0}{1}{2}", m_nCardIndex, nAxisNo, rtn));
                //LogView.GetInstance().ShowLog(LogView.LogType.Error, string.Format("雷赛控制卡Jog运动失败 卡号 轴号 原因{0}{1}{2}", m_nCardIndex, nAxisNo, rtn));
            }

        }

        /// <summary>
        /// 指定轴回原点 
        /// </summary>
        /// <param name="nAxisNo"></param>
        /// <param name="MoveDir"></param>
        /// <returns></returns>
        public override void HomeMove(int nAxisNo, int MoveDir, uint HomeMode)
        {
            //MODE1_Abs: Move(Dir)->touch ORG->Stop.
            //MODE2_Lmt: Move(Dir)->touch EL->Stop
            //MODE3_Ref: Move(Dir)->touch EZ->Stop
            //MODE4_Abs_Ref: ORG + EZ, Move(Dir)->touch ORG->Stop->Move(Dir)->touchEZ->Stop
            //MODE5_Abs_NegRef: ORG + EZ, Move(Dir)->touch ORG->Stop->Move(-Dir) -> touch EZ->Stop.
            //MODE6_Lmt_Ref: EL + NegEZ, Move(Dir)->touch EL->Stop->Move(-Dir) -> touch EZ->Stop.
            //MODE7_AbsSearch: Move(Dir)->Search ORG->Stop
            //MODE8_LmtSearch: Move(Dir)->Search EL->Stop.
            //MODE9_AbsSearch_Ref: Search ORG +EZ, Move(Dir)->Search ORG->Stop -> Move(Dir)->touch EZ->Stop.
            //MODE10_AbsSearch_NegRef: Search ORG +NegEZ, Move(Dir)->Search ORG -> Stop->Move(-Dir)->touch EZ->Stop.
            //MODE11_LmtSearch_Ref: Search EL +NegEZ, Move(Dir)->Search EL->Stop -> Move(-Dir)->touch EZ->Stop.
            //MODE12_ AbsSearchRefind: Search ORG +Refind ORG, Move(Dir)->SearchORG->Stop->Move(-Dir)->Leave ORG(FL)->Stop->Move(-Dir)->RefindORG(FL)->Stop.
            //MODE13_ LmtSearchRefind: Search EL +Refind EL, Move(Dir)->Search EL -> Stop->Move(-Dir)->Leave EL(FL)->Stop->Move(-Dir)->Refind EL(FL) -> Stop.
            //MODE14_AbsSearchRefind_Ref: Search ORG +Refind ORG + EZ, Move(Dir) -> Search ORG->Stop->Move(-Dir)->Leave ORG(FL)->Stop->Move(-Dir) -> Refind ORG(FL)->Stop->Move(Dir)->touch EZ->Stop.
            //MODE15_AbsSearchRefind_NegRef: Search ORG +Refind ORG + NegEZ, Move(Dir)->Search ORG->Stop->Move(-Dir)->Leave ORG(FL)->Stop->Move(-Dir) -> Refind ORG(FL)->Stop->Move(-Dir)->touch EZ->Stop.
            //MODE16_LmtSearchRefind_Ref: Search EL +Refind EL + EZ, Move(Dir) -> Search EL->Stop->Move(-Dir)->Leave EL(FL)->Stop->Move(-Dir) -> Refind EL(FL)->Stop->Move(-Dir)->touch EZ->Stop.
         
            double acc = SystemCfg.AxisCfg[nAxisNo].Acc * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//加速时间
            double dec = SystemCfg.AxisCfg[nAxisNo].Dec * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//减速时间
            double start = SystemCfg.AxisCfg[nAxisNo].StartSpeed * SystemCfg.AxisCfg[nAxisNo].PluseRatio;//起始速度
            double Hspeed = SystemCfg.AxisCfg[nAxisNo].OrgHSpeed * SystemCfg.AxisCfg[nAxisNo].PluseRatio;
            double Lspeed = SystemCfg.AxisCfg[nAxisNo].OrgLSpeed * SystemCfg.AxisCfg[nAxisNo].PluseRatio;
            double CrossDistance = SystemCfg.AxisCfg[nAxisNo].CrossDistance* SystemCfg.AxisCfg[nAxisNo].PluseRatio;
            Task task = new Task(() => 
            {
                //if (nAxisNo<12)
                //{
                //    AxisList[(ushort)nAxisNo].HomeByMoveHome(start, Hspeed, acc, acc, HomeMode, (uint)MoveDir, CrossDistance);
                //}
                //else
                //{
                    AxisList[(ushort)nAxisNo].HomeByAxHome(start, Hspeed, acc, acc, HomeMode, (uint)MoveDir, CrossDistance);
                //}
               
            });
           task.Start();           
        }
        public override bool HomeOK(int nAxisNo)
        {
            return AxisList[(ushort)nAxisNo].IsHome;
        
        }
        public override void InitExtIoCard(int CarsNO)
        {
            //short rtn = 0;
            //rtn = LTDMC.dmc_soft_reset((ushort)m_nCardIndex, (ushort)nIndex);//读取使能状态 0 低电平有效接通 1高电平高电平无效 取值范围0 -15
        }

        public override void DeInitExtIoCard(int Card)
        {
            throw new NotImplementedException();
        }

        public override bool ReadExtIn(int AxisID, int nIndex)
        {
            return AxisList[AxisID-1].GetAxisDI((ushort)nIndex);
        }

        public override bool ReadExtOut(int AxisID, int nIndex)
        {
            return AxisList[AxisID- 1].GetAxisDO((ushort)nIndex);
        }

        public override void WriteExtOut(int AxisID, int nIndex, bool bBit)
        {
            byte b;
            if (bBit)
            {
                b = 1;
            }
            else 
            {
                b = 0;
            }
           AxisList[AxisID-1].SetAxisDO((ushort)nIndex, b);
        }

        public override bool GetBusState()
        {
            //StringBuilder ErrorMsg = new StringBuilder("", 100);
            //int rtn = 0;
            //ushort code = 0;
            ////读取 EtherCAT 总线状态
            ////控制卡卡号  EtherCat总线端口号 固定为2 EtherCat 总线状态 0 表示正常
            ///
            //getlasterror
            //rtn = Motion.mAcm_GetErrorMessage(errorCode, ErrorMsg, 100);
            //if (rtn == 0)
            //{
            //    if (code == 0)
            //    {
            return true;
            //    }
            //}
            ////  MessageBox.Show(string.Format("雷赛控制总线报警 原因{0}", rtn));
            //// LogView.GetInstance().ShowLog(LogView.LogType.Error, string.Format("雷赛控制总线报警 卡号 轴号 原因{0}", m_nCardIndex, rtn));
            //return false;
        }

        public override void ClearBusAlarm()
        {
            //清除 EtherCAT 总线错误码
            int rtn = 0;
            //CardNo 控制卡卡号  PortNum EtherCAT 总线端口号，固定为 2

            rtn = LTDMC.nmc_clear_errcode((ushort)m_nCardIndex, 2);
            if (rtn != 0)
            {
                MessageBox.Show(string.Format("雷赛控制清除总线报警失败 原因{0}", rtn));
                LogView.GetInstance().ShowLog(LogView.LogType.Error, string.Format("雷赛控制清除总线报警失败 卡号 轴号 原因{0}", m_nCardIndex, rtn));
            }
        }

        public override bool HomeMove1(int nAxisNo, int MoveDir)
        {
            throw new NotImplementedException();
        }


        #region 比较输出   1274卡
        /// <summary>
        /// 打开位置比较功能
        /// </summary>
        /// <param name="cardNum"></param>
        /// <param name="channel"></param>
        /// <param name="dir"></param>
        public override void OpenCmd(int cardNum, ushort channel, uint dir)
        {
            uint ret;
            if (Motion.mAcm_DevEnableCmp(m_DeviceHandleList[cardNum], channel, 2)!=0)
            {
                return;
            }
           ;//使能
            if (Motion.mAcm_DevEnableCmpFIFO(m_DeviceHandleList[cardNum], channel, 1)!=0)
            {
                return;
            }
            ;//使能FIFO功能

            //Smaller - 1 Greater - 0
            if (Motion.mAcm_DevSetCmp(m_DeviceHandleList[cardNum], channel, 1, 1, dir, 0, 10)!=0)
            {
                return;
            }
            ;//设置触发

        }
        /// <summary>
        /// 关闭位置比较功能，关闭轴卡时使用
        /// </summary>
        /// <param name="cardNum"></param>
        /// <param name="channel"></param>
        public override void CloseCmd(int cardNum, ushort channel)
        {
            Motion.mAcm_DevSetCmpDO(m_DeviceHandleList[cardNum], channel, 0);

            Motion.mAcm_DevEnableCmp(m_DeviceHandleList[cardNum], channel, 0);//使能
            Motion.mAcm_DevEnableCmpFIFO(m_DeviceHandleList[cardNum], channel, 0);//使能FIFO功能
        }
        /// <summary>
        /// 设置位置比较触发时的脉冲
        /// </summary>
        /// <param name="cardNum"></param>
        /// <param name="channel"></param>
        /// <param name="data"></param>
        public override void SetCmdData(int cardNum, ushort channel, double[] data)
        {
            for (int i = 0; i < data.Length; i++)
            {
                if (Motion.mAcm_DevSetCmpData(m_DeviceHandleList[cardNum], channel, data[i])!=0)
                {
                    return;
                }
                 
            }
        }
        /// <summary>
        /// 获取位置比较输出的状态
        /// </summary>
        /// <param name="cardNum"></param>
        /// <param name="channel"></param>
        /// <returns></returns>
        public override int GetCmdFIFOCount(int cardNum, ushort channel)
        {
            ushort count = 0;

            try
            {
                Motion.mAcm_DevGetCmpFIFOCount(m_DeviceHandleList[cardNum], channel, ref count);
            }
            catch (Exception)
            {

               
            }
           

            return count;
        }
        /// <summary>
        /// 打开位置比较通道的IO
        /// </summary>
        /// <param name="cardNum"></param>
        /// <param name="channel"></param>
        public override void SetCmdDO(int cardNum, ushort channel)
        {
            Motion.mAcm_DevSetCmpDO(m_DeviceHandleList[cardNum], channel, 1);//打开 Compare 输出
        }
        /// <summary>
        /// 关闭位置比较通道的IO
        /// </summary>
        /// <param name="cardNum"></param>
        /// <param name="channel"></param>
        public override void CloseCmdDO(int cardNum, ushort channel)
        {
            Motion.mAcm_DevSetCmpDO(m_DeviceHandleList[cardNum], channel, 0);//关闭 Compare 输出
        }
        /// <summary>
        /// 清除位置比较的状态
        /// </summary>
        /// <param name="cardNum"></param>
        /// <param name="channel"></param>
        public override void ResetCmd(int cardNum, ushort channel)
        {
            Motion.mAcm_DevResetCmpFIFO(m_DeviceHandleList[cardNum], channel);//重置指定比较通道的 FIFO 数据。
            Motion.mAcm_DevResetCmpData(m_DeviceHandleList[cardNum], channel);//清除比较器中的当前比较数据。
            Motion.mAcm_DevResetCmpFlag(m_DeviceHandleList[cardNum], channel);//清除比较器中的当前比较状态。
        }



        #endregion

    }

  





  
 
   
}
